namespace test1 {
  type Primitive = string | boolean | number | symbol | bigint | null | undefined;

  const isPrimitive = (val: any): val is Primitive => {
    if (val === null || val === undefined) {
      return true;
    }
    switch (typeof val) {
      case 'string':
      case 'boolean':
      case 'number':
      case 'symbol':
        return true;
      default:
        return false;
    }
  };

  type Falsy = false | '' | 0 | null | undefined;
  const isFalsy = (val: any): val is Falsy => !val;

  type Nullish = null | undefined;
  const isNullish = (val: any): val is Nullish => val == null;

  type NonNullable<T> = T extends Nullish ? never : T;
  type NonUndefined<T> = T extends undefined ? never : T;

  type Exclude<T, U> = T extends U ? never : T;
  type Extract<T, U> = T extends U ? T : never;

  type FunctionKeys<T extends object> = {
    [K in keyof T]-?: T[K] extends Function ? K : never;
  }[keyof T];

  type NonFunctionKeys<T extends object> = {
    [K in keyof T]-?: T[K] extends Function ? never : K;
  }[keyof T];

  type Pick<T extends object, K extends keyof T> = {
    [Key in K]: T[Key];
  };

  type PickByValue<T extends object, val> = Pick<
    T,
    { [K in keyof T]: T[K] extends val ? K : never }[keyof T]
  >;

  // 难点：怎么判断两个类型是一模一样的？ 双重extends判断(元组类型)
  type PickByValueExact<T extends object, val> = Pick<
    T,
    {
      [K in keyof T]: [val] extends [T[K]] ? ([T[K]] extends [val] ? K : never) : never;
    }[keyof T]
  >;

  type aa = number extends number | string ? 'a' : 'b';
  type bb = [number | string] extends [number | string] ? 'a' : 'b';
  type cc = [number | string];

  type DeepPartial<T> = T extends (...args: any[]) => any
    ? T
    : T extends object
    ? _DeepPartial<T>
    : T;

  type _DeepPartial<T> = {
    [K in keyof T]?: DeepPartial<T[K]>;
  };
  // Omit 忽略的意思
  type Omit<T extends object, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

  type RequiredKeys<T extends object> = {
    [K in keyof T]: {} extends Pick<T, K> ? never : K;
  }[keyof T];

  type OptionalKeys<T extends object> = {
    [K in keyof T]: {} extends Pick<T, K> ? K : never;
  }[keyof T];

  type Partial<T> = {
    [K in keyof T]?: T[K];
  };

  type Optional<T extends object, K extends keyof T = keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

  type Record<T extends keyof any, U> = {
    [K in T]: U;
  };

  type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

  interface Person {
    name: string;
    age: number;
    a?: number;
    obj: {
      aa: number;
      bb: string;
    };
    func(a: string): number;
    func1(): void;
  }

  type P1 = DeepPartial<Person>;
  const p: P1 = {
    obj: {
      aa: 11,
    },
  };

  type f1 = FunctionKeys<Person>;
  type f2 = NonFunctionKeys<Person>;
}
